<template>
  <div :class="[`rule-${mode}`]" :ref="`rule-${mode}`">
    <canvas :id="ruleId"></canvas>
    <div class="lines">
      <div
        class="line"
        v-for="(item, index) in lineArr"
        :key="index"
        :style="{ top: item.top + 'px', left: item.left + 'px', ...styleBorder, display: item.value >= 0 ? '' : 'none' }"
        :aria-left="item.left"
        :aria-top="item.top"
        :aria-value="Math.round(item.value)"
        @mouseenter="handleEnterLeave(item.value)"
        @mouseleave="handleEnterLeave()"
        @mousedown="handleMouseDown(item.value)"
      >
        <div class="anction">
          <span
            class="del"
            :style="{ visibility: showAnctionValue === item.value ? 'visible': 'hidden' }"
            @click="handleDelete(item.value)"
          >x</span>
          <span class="value">{{ Math.round(item.value) }}</span>
        </div>
      </div>
    </div>
    <div class="indicator" v-show="showIndicator" :style="styleBorder">
      <div class="value">{{ Math.round(showValue) }}</div>
    </div>
  </div>
</template>
<script>
export default {
  name: 'SketchRule',
  props: {
    mode: {
      type: String,
      default: 'horizontal'
    },
    width: {
      type: Number
    },
    height: {
      type: Number
    },
    configColor: {
      type: Object,
      default: () => {
        return {
          fillStyle: '#666',
          strokeStyle: '#666',
          font: 16,
          lineWidth: 1
        }
      }
    },
    scale: { // 缩放
      type: Number,
      default: 1
    },
    layout: {
      type: Array,
      default: () => []
    },
    perspective: { // 刻度尺跟随滚动条移动偏移量
      type: Number,
      default: 0
    }
  },
  computed: {
    ruleId () {
      return Math.random().toFixed(16) + '-' + this.mode
    },
    hv () {
      return this.$refs[`rule-${this.mode}`].querySelector('.indicator')
    },
    vertical () {
      return this.mode === 'horizontal'
    },
    styleBorder () {
      const { width, color, type } = this.lineConfig
      const border = `${width}px ${type} ${color}`
      return this.vertical ? { borderLeft: border } : { borderTop: border }
    },
    lock () {
      return document.querySelector('.rule-panel-lock').getBoundingClientRect()
    },
    $Q () {
      let scale = 10
      let text = 10
      if (this.scale < 0.1) {
        text = 80
      } else if (this.scale >= 0.1 && this.scale <= 0.25) {
        text = 40
      } else if (this.scale > 0.25 && this.scale <= 0.5) {
        text = 20
      } else if (this.scale > 0.5 && this.scale <= 1) {
        text = 10
      } else if (this.scale > 1 && this.scale <= 3) {
        text = 5
      }
      scale = text * this.scale
      return { scale, text }
    }
  },
  watch: {
    canvasWidth (val, oldVal) {
      if (oldVal) {
        this.horizontalValue = val - oldVal
      }
    },
    layout () {
      this.handleUpdate()
    },
    perspective () {
      this.handleUpdate()
    },
    scale () {
      this.handleUpdate()
    }
  },
  data () {
    return {
      config: { // 刻度尺配置
        size: 101,
        x: 0,
        y: 0,
        w: 10,
        h: 10,
        width: 20,
        height: 20,
        fillStyle: '#fff',
        strokeStyle: '#fff',
        font: 12,
        lineWidth: 1
      },
      cxt: null,
      canvas: null,
      showIndicator: false,
      showValue: 0,
      lineArr: [],
      showAnctionValue: 0,
      startValue: null,
      lineConfig: { // 拖拽线的样式
        color: '#51d6a9',
        type: 'dashed',
        width: 1
      },
      canvasWidth: 0,
      horizontalValue: 0
    }
  },
  mounted () {
    // window.addEventListener('resize', this.getWrapperSize)
    this.$nextTick(() => {
      this.initDom()
    })
  },
  methods: {
    initDom () {
      this.canvas = document.getElementById(this.ruleId)
      this.config = Object.assign(this.config, this.configColor)
      if (!this.canvas) return
      this.cxt = this.canvas.getContext('2d')
      this.initBindEvent()
      this.initConfig()
      this.draw(this.cxt, this.config)
    },
    initConfig () {
      const { width, height } = document.querySelector('.editor-render-top').getBoundingClientRect()
      this.warpOffset = document.querySelector('.ruler')?.getBoundingClientRect()
      const iconOffSet = this.lock.width
      this.canvasWidth = width
      const numLength = this.perspective
      const dom = document.querySelector('.ruler')
      dom.style.height = height + 'px'
      this.config.width = this.vertical ? 20 : iconOffSet
      this.config.height = this.vertical ? iconOffSet : 20
      const Width = this.vertical ? width - iconOffSet + numLength : this.config.width
      const Height = this.vertical ? this.config.height : height - iconOffSet + numLength
      const Size = this.vertical ? Width : Height
      this.canvas.setAttribute('width', Width)
      this.canvas.setAttribute('height', Height)
      this.config.size = Math.ceil((Math.ceil(Size / 10 * 40)) + 1)
    },
    initBindEvent () {
      this.handleMouseenter()
      this.handleMouseleave()
      this.handleMousemove()
      this.handleMouseClick()
    },
    getScale () {
    },
    draw (cxt, config) {
      const scale = this.scale
      const size = config.size || 101
      const x = config.x || 0
      const y = config.y || 0
      const w = config.w || 10
      const h = config.h || 10
      const v = this.mode || 'horizontal'
      cxt.clearRect(0, 0, config.width, config.height)
      cxt.strokeStyle = config.strokeStyle
      cxt.lineWidth = config.lineWidth / (this.scale * 1.5)
      cxt.font = `${12}px -apple-system,
                "Helvetica Neue", ".SFNSText-Regular",
                "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB",
                "Microsoft YaHei", "WenQuanYi Zen Hei", sans-serif`
      cxt.fillStyle = config.fillStyle
      for (let i = 0; i < size; i++) {
        cxt.beginPath()
        if (v == 'vertical') {
          const startY = y - this.perspective + i * this.$Q.scale
          cxt.moveTo(x, startY)
          if (i % 10 == 0) {
            cxt.save()
            cxt.translate(10, -10)
            cxt.rotate(90 * Math.PI / 180)
            cxt.fillText(x + i * this.$Q.text, x + w * 1.2 + i * this.$Q.scale - this.perspective, y)
            cxt.restore()
            cxt.lineTo(x + w * 1.3, x + i * this.$Q.scale - this.perspective)
          } else {
            cxt.lineTo(x + (i % 5 === 0 ? 0.8 : 0.5) * w, startY)
          }
          cxt.scale(1, scale)
        } else {
          const startX = (x - this.perspective) + i * this.$Q.scale
          cxt.moveTo(startX, y)
          if (i % 10 == 0) {
            cxt.fillText(x + i * this.$Q.text, startX + 2, y + h * 1.8)
            cxt.lineTo(startX, y + h * 1.3)
          } else {
            cxt.lineTo(startX, y + (i % 5 === 0 ? 0.8 : 0.5) * h)
          }
          cxt.scale(scale, 1)
        }
        cxt.stroke()
        cxt.closePath()
        cxt.setTransform(1, 0, 0, 1, 0, 0)
      }
    },
    getWrapperSize () {
      if (!this.canvas) return
      this.initConfig()
      this.draw(this.cxt, this.config)
    },
    setPosition ({ offsetX, offsetY }) {
      if (this.vertical) {
        this.hv.style.left = offsetX + 'px'
        this.showValue = (offsetX + this.perspective) / this.scale
      } else {
        this.hv.style.top = offsetY + 'px'
        this.showValue = (offsetY + this.perspective) / this.scale
      }
    },
    handleMouseenter () {
      this.canvas.onmouseenter = e => {
        if (this.startValue) return
        this.showIndicator = true
        this.setPosition(e)
      }
    },
    handleMouseleave () {
      this.canvas.onmouseleave = () => {
        this.showIndicator = false
      }
    },
    handleMousemove () {
      this.canvas.onmousemove = e => {
        if (this.startValue) return
        this.setPosition(e)
      }
    },
    // 点击出现对齐线
    handleMouseClick () {
      this.canvas.onclick = e => {
        const { offsetX, offsetY } = e
        if (this.vertical) {
          !this.lineArr.includes(offsetX) && this.lineArr.push({
            top: 0,
            left: offsetX,
            value: (offsetX + this.perspective) / this.scale
          })
        } else {
          !this.lineArr.includes(offsetY) && this.lineArr.push({
            top: offsetY,
            left: 0,
            value: (offsetY + this.perspective) / this.scale
          })
        }
      }
    },
    handleEnterLeave (value = 0) {
      this.showAnctionValue = value
    },
    handleDelete (e) {
      const index = this.lineArr.findIndex(k => k.value === e)
      this.lineArr.splice(index, 1)
    },
    handleMouseDown (e) {
      this.startValue = e
      document.addEventListener('mousemove', this.handleMove)
      document.addEventListener('mouseup', this.handleMouseUp)
    },
    handleMouseUp () {
      // const warpCanvasWidthHeight = this.vertical
      //   ? Math.floor(this.canvas.getAttribute('width')) / this.scale - this.lock.width - 3
      //   : Math.floor(this.canvas.getAttribute('height')) / this.scale - this.lock.width - 1
      // this.lineArr = this.lineArr.filter(e => e.value < warpCanvasWidthHeight / this.scale && e.value >= 0)
      this.startValue = null
      document.removeEventListener('mousemove', this.handleMove)
      document.removeEventListener('mouseup', this.handleMouseUp)
    },
    setStyle (e) { // e = { color: 'red', type: 'dashed', width: 1 }
      this.lineConfig = Object.assign(this.lineConfig, e)
    },
    // 拖动已经显示的对齐线移动
    handleMove (e) {
      e.stopPropagation()
      e.preventDefault()
      const { clientX, clientY } = e
      const iconOffSet = this.lock.width
      const left = this.vertical ? Math.round(clientX - this.warpOffset.left - iconOffSet) : 0
      const top = this.vertical ? 0 : Math.round(clientY - this.warpOffset.top - iconOffSet)
      const value = this.vertical
        ? Math.round((clientX - this.warpOffset.left - iconOffSet + this.perspective) / this.scale)
        : Math.round((clientY - this.warpOffset.top - iconOffSet) + this.perspective / this.scale)
      const index = this.lineArr.findIndex(k => Math.abs(k.value - this.startValue) <= 3)
      this.startValue = value
      this.showAnctionValue = value
      index >= 0 && this.$set(this.lineArr, index, { top, left, value })
    },
    listenMouseMove (e) {

    },
    handleScrollSetine () {
      if (!this.lineArr.length) return
      this.lineArr.forEach((e, i) => {
        const valueMax = (Math.round(e.value)) * this.scale - this.perspective
        this.$set(this.lineArr, i, {
          top: this.vertical ? 0 : valueMax,
          left: this.vertical ? valueMax : 0,
          value: Math.round(e.value)
        })
      })
    },
    handleUpdate () {
      if (!this.canvas) return
      this.initConfig()
      this.draw(this.cxt, this.config)
      this.handleScrollSetine()
    }
  },
  beforeDestroy () {
    window.removeEventListener('resize', this.getWrapperSize)
  }
}
</script>

<style lang="less" scoped>
@import "../../styles/vars.less";
.rule-horizontal {
  position: absolute;
  left: 24px;
  width: calc(100% - 24px);
  font-size: 12px;
  // overflow: hidden;
  .lines {
    .line {
      position: absolute;
      top: 0;
      cursor: ew-resize;
      height: 100vh;
      padding-left: 5px;
      z-index: 1;
      .anction {
        position: absolute;
        top: 24px;
        display: flex;
        justify-content: center;
        align-items: center;
        user-select: none;
        .del {
          padding: 0;
          font-size: 20px;
          font-weight: 600;
          cursor: pointer;
        }
        .value {
          pointer-events: none;
          margin-left: 5px;
          transform: translateY(3px);
        }
      }
    }
  }
  .indicator {
    position: absolute;
    pointer-events: none;
    top: 0;
    height: 100vh;
    z-index: 1;
    .value {
      position: absolute;
      width: auto;
      padding: 0 2px;
      margin-top: 4px;
      margin-left: 4px;
    }
  }
}
.rule-vertical {
  position: absolute;
  top: 24px;
  width: 24px;
  height: calc(100% - 24px);
  font-size: 12px;
  // overflow: hidden;
  .lines {
    .line {
      position: absolute;
      top: 0;
      cursor: ns-resize;
      width: 100vw;
      padding-top: 5px;
      z-index: 1;
      .anction {
        position: absolute;
        left: 24px;
        display: flex;
        justify-content: center;
        align-items: center;
        user-select: none;
        .del {
          padding: 0;
          font-size: 20px;
          font-weight: 600;
          cursor: pointer;
        }
        .value {
          pointer-events: none;
          margin-left: 5px;
          transform: translateY(3px);
        }
      }
    }
  }
  .indicator {
    position: absolute;
    pointer-events: none;
    top: 0;
    width: 100vw;
    z-index: 1;
    .value {
      position: absolute;
      left: 0;
      width: auto;
      padding: 0 2px;
      margin-top: -5px;
      margin-left: 2px;
      transform: rotate(-90deg);
      transform-origin: 0 0;
    }
  }
}
canvas {
  background: lighten(@dark-color, 15.9% - lightness(@dark-color));
  pointer-events: auto;
}
</style>